"""
大模型集成对话系统后端主应用

这是整个后端系统的入口文件，负责：
1. 初始化 FastAPI 应用
2. 配置中间件（CORS、安全等）
3. 注册 API 路由
4. 设置全局异常处理
5. 管理应用生命周期（启动/关闭）

作者: LLM Chat System
版本: 1.0.0
"""

from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware
from fastapi.middleware.trustedhost import TrustedHostMiddleware
from fastapi.responses import JSONResponse, Response
from fastapi.staticfiles import StaticFiles
import time
from contextlib import asynccontextmanager

# 导入配置和数据库模块
from app.core.config import settings
from app.database import init_db, close_db
# 导入 API 路由
from app.api.v1 import api_router
# 导入日志配置
from app.core.logging_config import setup_logging, app_logger

# 全局MCP状态管理
class MCPManager:
    """MCP全局状态管理器"""
    def __init__(self):
        self.is_initialized = False
        self.available_servers = []
        self.default_server_url = settings.mcp_server_url
    
    def set_initialized(self, status: bool):
        """设置MCP初始化状态"""
        self.is_initialized = status
    
    def add_server(self, server_url: str):
        """添加可用的MCP服务器"""
        if server_url not in self.available_servers:
            self.available_servers.append(server_url)
    
    def get_status(self):
        """获取MCP状态"""
        return {
            "initialized": self.is_initialized,
            "default_server": self.default_server_url,
            "available_servers": self.available_servers
        }

# 创建全局MCP管理器实例
mcp_manager = MCPManager()


@asynccontextmanager
async def lifespan(app: FastAPI):
    """
    应用生命周期管理器
    
    负责应用启动和关闭时的资源管理：
    - 启动时：初始化日志系统、数据库连接、MCP客户端
    - 关闭时：清理数据库连接、MCP客户端、释放资源
    
    Args:
        app: FastAPI 应用实例
    """
    # 启动时执行的操作
    setup_logging()  # 初始化日志系统
    app_logger.info("开始初始化应用")
    init_db()        # 初始化数据库连接和表结构
    app_logger.info("数据库初始化完成")
    
    # 初始化MCP相关组件
    try:
        from app.core.mcp.client import MCPClient
        from app.services.mcp_client_service import MCPClientService
        mcp_manager.set_initialized(True)
        app_logger.info("MCP组件初始化完成")
    except Exception as e:
        mcp_manager.set_initialized(False)
        app_logger.warning(f"MCP组件初始化失败: {str(e)}")
    
    app_logger.info("应用启动完成")
    
    yield  # 应用运行期间
    
    # 关闭时执行的操作
    app_logger.info("开始关闭应用")
    
    # 清理MCP客户端连接
    try:
        from app.services.mcp_client_service import MCPClientService
        # 关闭所有活跃的MCP客户端
        for client_id, client in MCPClientService._active_clients.items():
            try:
                await client.disconnect()
                app_logger.info(f"已关闭MCP客户端: {client_id}")
            except Exception as e:
                app_logger.warning(f"关闭MCP客户端失败: {client_id}, 错误: {str(e)}")
        MCPClientService._active_clients.clear()
        app_logger.info("MCP客户端清理完成")
    except Exception as e:
        app_logger.warning(f"MCP客户端清理失败: {str(e)}")
    
    close_db()       # 关闭数据库连接
    app_logger.info("数据库连接已关闭")
    app_logger.info("应用关闭完成")


# 创建 FastAPI 应用实例
app = FastAPI(
    title=settings.app_name,                    # 应用名称
    version=settings.app_version,                # 应用版本
    description="基于 FastAPI + LangChain + MySQL + Chroma 的大模型集成对话系统",
    lifespan=lifespan,                          # 生命周期管理器
    docs_url="/docs" if settings.debug else None,    # API 文档地址（仅调试模式）
    redoc_url="/redoc" if settings.debug else None   # ReDoc 文档地址（仅调试模式）
)

# 添加 CORS（跨域资源共享）中间件
# 允许前端应用访问后端 API
app.add_middleware(
    CORSMiddleware,
    allow_origins=[
        "http://localhost:5173", 
        "http://localhost:5174", 
        "http://127.0.0.1:5173", 
        "http://127.0.0.1:5174",
        "http://localhost:3000",
        "http://127.0.0.1:3000"
    ],  # 允许的源地址
    allow_credentials=True,                # 允许携带认证信息
    allow_methods=["GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"],  # 允许的HTTP方法
    allow_headers=["*"],                    # 允许所有请求头
    expose_headers=["*"],                   # 暴露的响应头
    max_age=3600                            # 预检请求缓存时间
)

# 添加受信任主机中间件
# 防止 Host 头攻击
app.add_middleware(
    TrustedHostMiddleware,
    allowed_hosts=["*"] if settings.debug else ["localhost", "127.0.0.1"]
)

# 添加专门的OPTIONS请求处理器
@app.options("/{full_path:path}")
async def options_handler(request: Request, full_path: str):
    """
    处理所有OPTIONS请求（CORS预检请求）
    """
    return Response(
        status_code=200,
        headers={
            "Access-Control-Allow-Origin": request.headers.get("origin", "*"),
            "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS, PATCH",
            "Access-Control-Allow-Headers": "Content-Type, Authorization, X-Requested-With",
            "Access-Control-Allow-Credentials": "true",
            "Access-Control-Max-Age": "86400",
        }
    )


@app.middleware("http")
async def logging_middleware(request: Request, call_next):
    """
    HTTP请求日志中间件
    
    记录所有HTTP请求和响应的详细信息，包括：
    - 请求方法、路径、状态码
    - 处理时间
    - 客户端IP和User-Agent
    - 错误信息（如果有）
    
    Args:
        request: HTTP 请求对象
        call_next: 下一个中间件或路由处理器
        
    Returns:
        添加了处理时间头的 HTTP 响应
    """
    start_time = time.time()
    
    # 获取客户端信息
    client_ip = request.client.host if request.client else "unknown"
    user_agent = request.headers.get("user-agent", "unknown")
    
    # 记录请求开始 - 添加到控制台和日志文件
    print(f"[HTTP请求开始] {request.method} {request.url.path} - IP: {client_ip}")
    app_logger.info(f"收到请求: {request.method} {request.url.path} - IP: {client_ip}")
    
    try:
        # 处理请求
        response = await call_next(request)
        process_time = time.time() - start_time
        
        # 打印到控制台
        print(f"[HTTP请求完成] {request.method} {request.url.path} - {response.status_code} - {process_time:.3f}s")
        
        # 记录成功请求日志
        app_logger.http_request(
            method=request.method,
            path=request.url.path,
            status_code=response.status_code,
            duration=process_time,
            client_ip=client_ip,
            user_agent=user_agent
        )
        
        # 添加处理时间头
        response.headers["X-Process-Time"] = str(process_time)
        
        return response
        
    except Exception as e:
        process_time = time.time() - start_time
        
        # 打印到控制台
        print(f"[HTTP请求错误] {request.method} {request.url.path} - {str(e)}")
        
        # 记录错误请求日志
        app_logger.error(f"请求处理异常: {request.method} {request.url.path} - {str(e)}")
        
        # 返回错误响应
        return JSONResponse(
            status_code=500,
            content={"detail": "内部服务器错误"},
            headers={"X-Process-Time": str(process_time)}
        )


@app.exception_handler(Exception)
async def global_exception_handler(request: Request, exc: Exception):
    """
    全局异常处理器
    
    捕获所有未处理的异常，记录日志并返回统一的错误响应
    确保应用不会因为未处理的异常而崩溃
    
    Args:
        request: 发生异常的请求对象
        exc: 异常对象
        
    Returns:
        统一的错误响应 JSON
    """
    # 使用自定义日志记录器记录异常
    app_logger.exception(f"全局异常: {request.method} {request.url.path}", exc_info=exc)
    
    return JSONResponse(
        status_code=500,
        content={
            "detail": "内部服务器错误",
            "error": str(exc) if settings.debug else "服务器内部错误"  # 调试模式下显示详细错误
        }
    )


# 注册 API 路由
# 将所有 v1 版本的 API 路由注册到应用中
app.include_router(api_router, prefix=settings.api_prefix)

# 添加静态文件服务
# 使用统一的静态文件服务，通过路径区分不同类型的文件
import os
from pathlib import Path

# 获取uploads目录的绝对路径
uploads_dir = Path("uploads").resolve()

# 添加专门的头像文件服务端点（必须在静态文件挂载之前注册）
@app.get("/static/avatars/{filename}")
async def serve_avatar(filename: str):
    """专门的头像文件服务端点"""
    from fastapi.responses import FileResponse
    from pathlib import Path
    
    # 构建文件路径
    avatar_path = Path("uploads/avatars") / filename
    
    if not avatar_path.exists():
        from fastapi import HTTPException
        raise HTTPException(status_code=404, detail="头像文件不存在")
    
    return FileResponse(
        path=str(avatar_path),
        media_type="image/png",
        filename=filename
    )

# 挂载静态文件服务（在其他静态文件之后）
app.mount("/static", StaticFiles(directory=str(uploads_dir)), name="static")


@app.get("/")
async def root():
    """
    根路径处理器
    
    返回应用的基本信息，包括：
    - 应用名称和版本
    - API 文档地址
    - API 前缀信息
    
    Returns:
        包含应用基本信息的 JSON 响应
    """
    return {
        "message": "大模型集成对话系统后端",
        "version": settings.app_version,
        "docs": "/docs" if settings.debug else "文档已禁用",
        "api_prefix": settings.api_prefix
    }


@app.get("/health")
async def health_check():
    """
    健康检查端点
    
    用于监控系统状态，返回：
    - 系统状态
    - 当前时间戳
    - 应用版本
    - MCP状态
    
    Returns:
        包含系统健康状态的 JSON 响应
    """
    return {
        "status": "healthy",
        "timestamp": time.time(),
        "version": settings.app_version,
        "mcp": mcp_manager.get_status()
    }


@app.get("/mcp/status")
async def mcp_status():
    """
    MCP状态检查端点
    
    返回MCP系统的详细状态信息
    
    Returns:
        包含MCP状态的 JSON 响应
    """
    return {
        "mcp_status": mcp_manager.get_status(),
        "timestamp": time.time()
    }


if __name__ == "__main__":
    import uvicorn
    
    uvicorn.run(
        "app.main:app",
        host="127.0.0.1",
        port=8001,
        reload=settings.debug,
        log_level=settings.log_level.lower()
    )
